import sys
import requests
import subprocess
import time
import os
from requests import exceptions

from bs4 import BeautifulSoup


pre = "https://kojipkgs.fedoraproject.org/packages/"


def procees_data():
    """
    处理输入数据
    Returns:
        pkg_list  软件包列表
        obs  obs本地仓库地址
        arch  寻找软件包的最低架构版本，默认为31。将往上最高寻找2个版本
    """
    file = ""
    obs = ""
    try:
        file = sys.argv[1]
        obs = sys.argv[2]
    except IndexError:
        print("Need to add the input txt.")
        exit()

    try:
        arch = int(sys.argv[3])
    except IndexError:
        arch = 31

    pkg_list = []
    with open(file) as f:
        for s in f:
            pkg_list.append(s.rstrip("\n"))
    return pkg_list, obs, arch


def get_download_url(name, arch_version):
    """
    获取单个软件包下载地址
    Args:
        name: 软件包名
        arch_version: 软件包适用的架构的版本

    Returns:
        download_url  软件包的下载地址
    """
    print("Processing %s" % name)

    # order_str 为此网页的url后缀，将软件包按修改顺序排列
    order_str = '?C=M;O=A'

    url_name = pre + name + "/"
    response_name = request_get(url_name)

    soup_name = BeautifulSoup(response_name.text, 'html.parser')

    # 给网站提供的所有版本好排序，获得最新的版本号
    tmp_version_list = [a.text for a in soup_name.find_all("a")]
    version_list = []
    for v in tmp_version_list:
        if v.endswith("/"):
            version_list.append(v[:-1])
    version = sorted(version_list, key=lambda x: float(x.split(".")[0] + "." + "".join(x.split(".")[1:])))[-1]
    url_version = pre + name + "/" + version + "/"

    response_version = request_get(url_version + order_str)
    soup_version = BeautifulSoup(response_version.text, 'html.parser')
    fc_version_list = soup_version.find_all("a")

    # 寻找所需版本的架构的软件包，默认fedora31。若找不到，则向上最多寻找两个版本。
    tmp_version = ""
    release_list = []
    for i in range(3):
        tmp_version = 'fc' + str(arch_version+i) + "/"
        for fc_v in fc_version_list:
            fc_v_text = fc_v.get_text()
            if fc_v_text.endswith(tmp_version):
                release_list.append(int(fc_v_text.split(".")[0]))
        if release_list:
            break

    # 此最新版本的软件包不支持所需要的版本的架构
    if not release_list:
        print("No available version")
        print('*'*70)
        return

    release_num = sorted(release_list)[-1]
    url_full = url_version + str(release_num) + '.' + tmp_version + "src/"

    response_full = request_get(url_full)
    soup_full = BeautifulSoup(response_full.text, 'html.parser')

    # 获取到网页最后一个链接地址，即为下载地址
    fc_full = soup_full.find_all("a")[-1].get_text()

    print("Pakcage's full name is " + fc_full)

    download_url = url_full + fc_full
    print("*" * 70)
    return download_url


def request_get(url):
    """
    访问网页
    Args:
        url: 访问网页的地址

    Returns:
        response: 网页response内容
    """
    try:
        t1 = time.time()
        response = requests.get(url, timeout=10)
        t2 = time.time()
    except exceptions.Timeout as e:
        print('Request timed out：'+str(e.response))
        raise
    except exceptions.HTTPError as e:
        print('http request wrong:'+str(e.response))
        raise
    else:
        # 通过status_code判断请求结果是否正确
        print('Request takes %s seconds' % (t2-t1))
        if response.status_code == 200:
            print('Connect successfully: 200')
            return response
        elif response.status_code == 404:
            print('Connection failed：'+str(response.status_code)+','+str(response.reason))
            raise RuntimeError("No package found!")
        else:
            print('Connection failed：'+str(response.status_code)+','+str(response.reason))
            raise RuntimeError("Internal sever error!")


def download_url_list(pkg_list, arch):
    """
    批量获取软件包下载地址，并将成功及失败结果存储到txt
    Args:
        pkg_list:
        arch:

    Returns:
    """
    success_list = []
    fail_list = []
    for pkg in pkg_list:
        try:
            full_url = get_download_url(pkg, arch)
            if full_url:
                success_list.append(full_url)
            else:
                fail_list.append(pkg)
        except exceptions.Timeout as e:
            fail_list.append(pkg)
            print(e.response)
            print('*' * 70)
        except RuntimeError as e:
            fail_list.append(pkg)
            print(e)
            print('*' * 70)
        except Exception as e:
            fail_list.append(pkg)
            print(e)
            print('*' * 70)

    with open("url.txt","w") as f:
        for url in success_list:
            f.write(url+'\n')

    with open("FailedPackage.txt","w") as f:
        for pkg in fail_list:
            f.write(pkg+'\n')

    print("%d packages' url are fetched. Failed %d packages" % (len(success_list),len(fail_list)))

    if fail_list:
        for p in fail_list:
            print(p)

def remove_blank(str):
    return str.replace("\n", "").replace("\r", "")

def import_srcrpm(obs_location):
    # 通过获取到的源码包url，将源码包下载、解压、上传到OBS中进行编译
    os.system("mkdir ./rpm_download_tmp")
    with open("url.txt", "r") as f:
        urls_temp = f.read()
        urls = urls_temp.splitlines()
        
        for url in urls:
            os.system("rm -rf ./rpm_download_tmp/*")
            # 下载源码包到指定路径
            print("[INFO] Downloading src_rpm by {}".format(url))
            commond_wget = "wget -P ./rpm_download_tmp {} >/dev/null 2>&1".format(url)
            download_result = os.system(commond_wget)
            if download_result != 0:
                print("[ERROR] download failed")
                continue
            else:
                print("[INFO] Download success")
            
            # 上传源码包到OBS
            src_rpm = os.popen("ls ./rpm_download_tmp")
            print("[INFO] Loading import {} to obs".format(remove_blank(src_rpm.read())))
            command_import = "osc importsrcpkg {} -p {} -c".format("./rpm_download_tmp/*", obs_location)
            import_result = subprocess.run(command_import,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE,encoding="utf-8")
            if import_result.returncode == 0:
                print("[INFO] Import {} success".format(remove_blank(src_rpm.read())))
            else:
                print("[ERROR] Import {} failed, reason: {}".format(remove_blank(src_rpm.read()),import_result.stderr))
            
            # os.system("rm -rf ./rpm_download_tmp/*")
            print('*' * 70)
    # os.system("rm -rf rpm_download_tmp")

if __name__ == "__main__":
    time_start = time.time()
    pkg_list, obs_location, arch = procees_data()
    download_url_list(pkg_list, arch)
    time_end = time.time()
    t = time_end - time_start
    print("Takes %s seconds totally" % t)
    print("Done!")
    print('#' * 70)
    import_srcrpm(obs_location)
